﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Microsoft.Live;
using SkyDriveAPI;
using System.Runtime.InteropServices;
using System.ServiceModel;
using System.Xml.Linq;

namespace INTEXReportSrv
{
    public partial class MainForm : Form, IRefreshTokenHandler
    {
        // Update the ClientID with your app client Id that you created from https://manage.dev.live.com.
        private const string ClientID = "00000000440E0BB5";
        private LiveAuthForm authForm;
        private LiveAuthClient liveAuthClient;
        public LiveConnectClient LiveClient;
        private RefreshTokenInfo refreshTokenInfo;
        public static log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        ServiceHost host;
        Watcher watcher = new Watcher();
        string[] scope;// =( "wl.basic wl.photos wl.skydrive wl.offline_access wl.signin wl.skydrive_update");
        ArrayList scopes = new ArrayList();
        public MainForm()
        {
            if (ClientID.Contains('%'))
            {
                throw new ArgumentException("Update the ClientID with your app client Id that you created from https://manage.dev.live.com.");
            }
            InitializeComponent();            
            scopes.Add("wl.basic");
            scopes.Add("wl.photos");
            scopes.Add("wl.skydrive");
            scopes.Add("wl.signin");
            scopes.Add("wl.skydrive_update");
            scope = new string[scopes.Count];
            scopes.CopyTo(scope);
            InitializeComponent();
            SigninButton_Click(null, null);
  
        }
        private async void MainForm_Load(object sender, EventArgs e)
        {
            this.methodComboBox.SelectedIndex = 0;
            try
            {         
                host = new ServiceHost(typeof(IntexReptServBL));
                host.Open();
            }
            catch (Exception ex)
            {
                this.LogOutput("Received an error during initializing. " + ex.Message);
            }
        }
        private LiveAuthClient AuthClient
        {
            get
            {
                if (this.liveAuthClient == null)
                {
                    this.AuthClient = new LiveAuthClient(ClientID, this);
                }

                return this.liveAuthClient;
            }

            set
            {
                if (this.liveAuthClient != null)
                {
                    this.liveAuthClient.PropertyChanged -= this.liveAuthClient_PropertyChanged;
                }

                this.liveAuthClient = value;
                if (this.liveAuthClient != null)
                {
                    this.liveAuthClient.PropertyChanged += this.liveAuthClient_PropertyChanged;
                }

                this.LiveClient = null;
            }
        }

        private LiveConnectSession AuthSession
        {
            get
            {
                return this.AuthClient.Session;
            }
        }

        private void liveAuthClient_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "Session")
            {
                this.UpdateUIElements();
            }
        }

        private void UpdateUIElements()
        {
            LiveConnectSession session = this.AuthSession;
            bool isSignedIn = session != null;
            this.signOutButton.Enabled = isSignedIn;
            this.connectGroupBox.Enabled = isSignedIn;
            this.currentScopeTextBox.Text = isSignedIn ? string.Join(" ", session.Scopes) : string.Empty;
            if (!isSignedIn)
            {
                this.meNameLabel.Text = string.Empty;
                this.mePictureBox.Image = null;
            }
        }

        private void SigninButton_Click(object sender, EventArgs e)
        {
            if (this.authForm == null)
            {
                string startUrl = this.AuthClient.GetLoginUrl(this.GetAuthScopes());
                string endUrl = "https://login.live.com/oauth20_desktop.srf";
                this.authForm = new LiveAuthForm(
                    startUrl,
                    endUrl,
                    this.OnAuthCompleted);
                this.authForm.FormClosed += AuthForm_FormClosed;
                this.authForm.ShowDialog(this);
            }
        }

        private string[] GetAuthScopes()
        {
            if (scope.Length == 0)
            {
                string[] scopes = new string[this.scopeListBox.SelectedItems.Count];
                this.scopeListBox.SelectedItems.CopyTo(scopes, 0);
                return scopes;
            }
            else
            {
                return scope;
            }
        }

        void AuthForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            this.CleanupAuthForm();
        }

        private void CleanupAuthForm()
        {
            if (this.authForm != null)
            {
                this.authForm.Dispose();
                this.authForm = null;
            }
        }

        private void LogOutput(string text)
        {
//            this.outputTextBox.Text += text + "\r\n";
        }

        private async void OnAuthCompleted(AuthResult result)
        {
            this.CleanupAuthForm();
            if (result.AuthorizeCode != null)
            {
                try
                {
                    LiveConnectSession session = await this.AuthClient.ExchangeAuthCodeAsync(result.AuthorizeCode);
                    this.LiveClient = new LiveConnectClient(session);
                    LiveOperationResult meRs = await this.LiveClient.GetAsync("me");
                    dynamic meData = meRs.Result;
                    this.meNameLabel.Text = meData.name;

                    LiveDownloadOperationResult meImgResult = await this.LiveClient.DownloadAsync("me/picture");
                    this.mePictureBox.Image = Image.FromStream(meImgResult.Stream);
                    watcher.LiveClient = LiveClient;
                }
                catch (LiveAuthException aex)
                {
                    this.LogOutput("Failed to retrieve access token. Error: " + aex.Message);
                }
                catch (LiveConnectException cex)
                {
                    this.LogOutput("Failed to retrieve the user's data. Error: " + cex.Message);
                }
            }
            else
            {
                this.LogOutput(string.Format("Error received. Error: {0} Detail: {1}", result.ErrorCode, result.ErrorDescription));
            }
        }

        private void SignOutButton_Click(object sender, EventArgs e)
        {
            this.signOutWebBrowser.Navigate(this.AuthClient.GetLogoutUrl());
            this.AuthClient = null;
            this.UpdateUIElements();
        }

        private void ClearOutputButton_Click(object sender, EventArgs e)
        {
            this.outputTextBox.Text = string.Empty;
        }

        private void ScopeListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.signinButton.Enabled = this.scopeListBox.SelectedItems.Count > 0;
        }

        
        private async void ExecuteButton_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrWhiteSpace(this.pathTextBox.Text))
            {
                this.LogOutput("Path cannot be empty.");
                return;
            }

            try
            {
                string method = this.methodComboBox.Text;
                string filepath = this.pathTextBox.Text;
                string destpath = this.destPathTextBox.Text;
                string requestbody = this.requestBodyTextBox.Text;
                this.LiveClient.Execute(method, filepath, destpath, requestbody);

            }
            catch (Exception ex)
            {
                this.LogOutput("Received an error. " + ex.Message);
            }
        } 

        Task IRefreshTokenHandler.SaveRefreshTokenAsync(RefreshTokenInfo tokenInfo)
        {
            // Note: 
            // 1) In order to receive refresh token, wl.offline_access scope is needed.
            // 2) Alternatively, we can persist the refresh token.
            return Task.Factory.StartNew(() =>
            {
                this.refreshTokenInfo = tokenInfo;
            });
        }

        Task<RefreshTokenInfo> IRefreshTokenHandler.RetrieveRefreshTokenAsync()
        {
            return Task.Factory.StartNew<RefreshTokenInfo>(() =>
            {
                return this.refreshTokenInfo;
            });
        }

        private void button1_Click(object sender, EventArgs e)
        {
            watcher._BATCHVKVV(DateTime.Now);
        }
    }
}
